#!/usr/bin/python

"Code to support release engineering"

import re,time,os,sys

VERSIONFILE="version.py"
VERSIONFILE_CONTENT="""\
#!/usr/bin/python

# VERSION FILE AUTOMATICALLY GENERATED via releng.py

VERSION='%(version)s'
VERNUMBER=%(vernumber)s

SVNURL="$URL$"
SVNREV="$Rev$"
SVNVERSION="%(svnversion)s" # this is the output of 'svnversion'

RELDATE=%(date)r

try: # take out svn keyword magic, no need for it at runtime
	SVNURL=SVNURL[6:-13] # and take out 'version.py'
	SVNREV=SVNREV[6:-2]
except:pass

def version_summary():
	r='version = '+VERSION+'\\n'
	r+='vernumber = %%.6f\\n'%%VERNUMBER
	r+='svnurl = '+SVNURL+'\\n'
	r+='svnrev = r'+SVNREV+'\\n'
	r+='svnversion = r'+SVNVERSION+'\\n'
	r+='reldate = '+RELDATE
	return r

if __name__=="__main__":
	print version_summary()
"""

def version_as_str(major,minor,macro,note=None):
	"""
	>>> version_as_str(1,2,3)
	'1.02.3'
	>>> version_as_str(1,2,0)
	'1.02'
	>>> version_as_str(1,2,-1)
	'1.02.-1'
	>>> version_as_str(1,2,0,'beta')
	'1.02-beta'
	>>> version_as_str(1,2,1,'rc4')
	'1.02.1-rc4'
	"""
	r='%s.%d'%(major,int(minor))
	
	if macro: r+='.%s'%macro
	if note: r+='-'+note
	
	return r
	
def parse_version_str(s):
	"""
	>>> parse_version_str('1.2')
	(1, 2, 0, None)
	>>> parse_version_str('1.2.3')
	(1, 2, 3, None)
	>>> parse_version_str('1.2.-1-beta')
	(1, 2, -1, 'beta')
	>>> parse_version_str('1.2-rc4')
	(1, 2, 0, 'rc4')
	>>> parse_version_str('1.2.7-rc4')
	(1, 2, 7, 'rc4')
	>>> parse_version_str('0.-1.-1')
	(0, -1, -1, None)
	"""
	m=re.match('(\d+)\.(-?\d+)(?:\.(-?\d+))?(?:-(\w+))?',s)
	assert m, ('version re pattern did not match',s)
	major,minor,macro,note=m.groups()
	if macro==None: macro=0
	major,minor,macro=int(major),int(minor),int(macro)
	return major,minor,macro,note
	
def parse_version_file():
	s=open(VERSIONFILE).read()
	m=re.match(".*\nVERSION='(.*)'",s,re.S)
	assert m,('regexp did not match',s)
	(versionstr,)=m.groups()
	return parse_version_str(versionstr)
	
def write_version_file(major,minor,macro,svnversion,note=''):
	version=version_as_str(major,minor,macro,note=note)
	vernumber=version_as_formatted_float(major,minor,macro)
	date=time.strftime('%Y.%m.%d<%H:%M\'%S')
	fd=open(VERSIONFILE,'w')
	fd.write(VERSIONFILE_CONTENT%locals())
	fd.close()
	
def version_as_formatted_float(major,minor,macro):
	"""
	Note that this really returns a string of the float :)
	>>> version_as_formatted_float(1,2,-1)
	'-1'
	>>> version_as_formatted_float(1,2,0)
	'1.002000'
	>>> version_as_formatted_float(1,2,2)
	'1.002002'
	"""
	assert macro>=-1,macro
	if macro==-1: return str(-1)
	
	return '%.6f'%(major + 1e-3*minor + 1e-6*macro)

def init():
	from proc import exe
	assert not os.path.exists(VERSIONFILE), ('version file already here',VERSIONFILE)
	svnversion=exe('svnversion').strip()
	write_version_file(0,-1,-1,svnversion)
	exe('svn add '+VERSIONFILE)
	exe('svn propset svn:keywords "URL Rev" '+VERSIONFILE)
	exe('svn ci -m "Initial version file" ' + VERSIONFILE)
	exe('cat '+VERSIONFILE)
	
if __name__=='__main__':
	if 'init' in sys.argv:
		init()
	else:
		import doctest
		doctest.testmod()
